package com.qdxwx.web.controller.auth;

import com.qdxwx.common.cache.CacheUtils;
import com.qdxwx.common.constants.CacheConstants;
import com.qdxwx.common.json.AjaxResult;
import com.qdxwx.common.utils.TKConvert;
import com.qdxwx.common.utils.TKRequest;
import com.qdxwx.common.utils.TKString;
import com.qdxwx.common.wechat.WxLogin;
import com.qdxwx.common.wechat.WxToken;
import com.qdxwx.common.wechat.WxUserInfo;
import com.qdxwx.data.service.user.UserService;
import com.qdxwx.data.service.user.UserThirdService;
import com.qdxwx.data.service.website.WebsiteProfileService;
import com.qdxwx.models.enums.UserRegisterFrom;
import com.qdxwx.models.enums.UserThirdType;
import com.qdxwx.models.enums.WebsiteProfileType;
import com.qdxwx.models.user.User;
import com.qdxwx.models.user.UserThird;
import com.qdxwx.models.user.UserToken;
import com.qdxwx.web.controller.BaseController;
import com.qdxwx.web.utils.LoginUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;

@Controller
@RequestMapping("/auth/wechat")
public class WeChatLoginController extends BaseController {

    private static final Logger logger = LoggerFactory.getLogger(WeChatLoginController.class);

    public static final String SESSION_STATE_NAME = "third-login-state";
    public static final String SESSION_COMEURL_NAME = "third-login-comeurl";
    public static final String SESSION_PROFILE_NAME = "third-login-profile";

    @Autowired
    private UserThirdService userThirdService;
    @Autowired
    private WebsiteProfileService websiteProfileService;
    @Autowired
    private UserService userService;

    @RequestMapping("/login")
    public String weChatLogin(HttpServletRequest request) {
        //微信登录开关限制
        if (!"ON".equals(CacheConstants.WEIXIN_LOGIN_IS_OPEN)) {
            request.setAttribute("message", "暂不允许微信账号登录！");
            return VIEW_ERROR;
        }

        String base_url = "https://" + request.getServerName() + "/auth/wechat";
        String redirect_url;
        String state = TKString.createUUID();
        String comeUrl = TKRequest.getComeUrl(request);
        //设置State  comeUrl
        HttpSession session = request.getSession();
        session.setAttribute(SESSION_STATE_NAME, state);
        session.setAttribute(SESSION_COMEURL_NAME, TKConvert.toURLEncode(comeUrl));
        //获得 微信登录 配置
        Map<String, Object> wxConfig = websiteProfileService.getMap("wxLogin");

        if (WxLogin.isWxBrowser(request)) {
            //授权登陆页面
            redirect_url = URLEncoder.encode(base_url + "/snsapi", StandardCharsets.UTF_8);
            return "redirect:" + WxLogin.getLoginSnsUrl((String) wxConfig.get("snsAppId"), redirect_url, state);
        } else {
            redirect_url = URLEncoder.encode(base_url + "/return", StandardCharsets.UTF_8);
            return "redirect:" + WxLogin.getLoginUrl((String) wxConfig.get("appId"), redirect_url, state);
        }
    }

    /**
     * 微信登录回调(获取code参数)
     */
    @RequestMapping("/return")
    public String weChatLoginReturn(HttpServletRequest request, HttpServletResponse response, RedirectAttributes redirectAttributes) throws Exception {
        String code = request.getParameter("code");
        String state = request.getParameter("state");
        if (TKString.isEmpty(code) || TKString.isEmpty(state)) {
            return toErrorView(request, "获取返回的参数失败");
        }
        String sessionStage = (String) request.getSession().getAttribute(SESSION_STATE_NAME);
        if (sessionStage == null || !sessionStage.equals(state)) {
            return toErrorView(request, "状态码验证失败，请重新扫码！");
        }
        //获得 微信登录 配置
        Map<String, Object> wxConfig = websiteProfileService.getMap(WebsiteProfileType.wxLogin);
        //拼写微信获取access_token访问地址
        WxToken wxToken = WxLogin.getAccessToken((String) wxConfig.get("appId"),
                (String) wxConfig.get("appSecret"),
                code);
        if (wxToken == null) {
            return toErrorView(request, "获取返回的参数失败！");
        }
        return doWeChatLogin(request, response, wxToken);
    }

    //queryDoUserThreeLogin

    /**
     * 微信公众号 微信自带网页登录回调(获取code参数)
     * weChatWebpageLogin
     */
    @RequestMapping("/snsapi")
    public String weChatWebPageLoginReturn(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String code = request.getParameter("code");
        String state = request.getParameter("state");
        if (TKString.isEmpty(code) || TKString.isEmpty(state)) {
            return toErrorView(request, "获取返回的参数失败");
        }
        String sessionStage = (String) request.getSession().getAttribute(SESSION_STATE_NAME);
        if (sessionStage == null || !sessionStage.equals(state)) {
            return toErrorView(request, "状态码验证失败，请重新扫码！");
        }
        //获得 微信公众号 配置
        //获得 微信登录 配置
        Map<String, Object> wxConfig = websiteProfileService.getMap(WebsiteProfileType.wxLogin);
        //拼写微信获取access_token访问地址
        WxToken wxToken = WxLogin.getAccessToken((String) wxConfig.get("snsAppId"),
                (String) wxConfig.get("snsAppSecret"),
                code);
        if (wxToken == null) {
            return toErrorView(request, "获取返回的参数失败！");
        }
        return doWeChatLogin(request, response, wxToken);
    }

    /**
     * 如果没登陆过则执行绑定操作  如果登陆过执行登陆操作
     */
    private String doWeChatLogin(HttpServletRequest request, HttpServletResponse response, WxToken wxToken) {
        WxUserInfo userInfo = WxLogin.getUserInfo(wxToken);
        if (userInfo == null) {
            return toErrorView(request, "获取返回的参数失败！");
        }
        User user;
        long userId = 0;
        UserThird userThird = userThirdService.getByValue(userInfo.getUnionid());
        //如果已经绑定过账号则执行登陆方法
        if (userThird == null) {
            userThird = new UserThird();
            userThird.setValue(userInfo.getUnionid());
            userThird.setValueTwo(userInfo.getOpenid());
            userThird.setType(UserThirdType.WEIXIN.ordinal());
            userThird.setAvatar(userInfo.getHeadimgurl());
            userThird.setName(userInfo.getNickname());

            user = new User();
            //user.setMobile(mobile);
            user.setUserName(userThird.getName());
            user.setRealName(userThird.getName());
            user.setAvatar(userThird.getAvatar());
            user.setPassword(TKString.getRanString(8));
            user.setRegisterFrom(UserRegisterFrom.WEIXIN.toString());
            userId = userService.register(request, user);
            userThird.setUserId(userId);
            if (userThirdService.insert(userThird) < 1) {
                return toErrorView(request, "程序执行错误，请与客服联系");
            }
        } else {
            //重新设置openId，防止公众号微信支付时openId对不上
            userThird.setValueTwo(userInfo.getOpenid());
            //更新头像和名称
            userThird.setAvatar(userInfo.getHeadimgurl());
            userThird.setName(userInfo.getNickname());
            userThirdService.update(userThird);
        }

        HttpSession session = request.getSession();
        //从Session里获取来源地址
        String comeUrl = getComeUrl(session);
        //获取用户信息
        user = userService.get(userThird.getUserId());
        if (user == null) {
            return toErrorView(request, "找不到指定用户，请与本网客服联系！");
        }
        if (user.getIsAvailable() != 1) {
            return toErrorView(request, "帐号已被禁用！");
        }
        //清除Session
        clearLoginSession(session);
        UserToken token = userService.doLogin(request, user);
        LoginUser.setUser(request, user);
        LoginUser.setCookie(response, token);
        return "redirect:" + comeUrl;
        /*
        //如果已经登录(可用于用户中心绑定)
        userId = LoginUser.getUserId(request);
        if (userId > 0) {
            userThird.setUserId(userId);
            userThirdService.update(userThird);
            return "redirect:" + comeUrl;
        }
        //来源地址设置到模版引擎
        request.setAttribute("comeUrl", comeUrl);
        //userThird
        request.setAttribute("userThird", userThird);
        session.setAttribute(SESSION_PROFILE_NAME, userThird);
        //不需要跳转，直接模板
        if (TKRequest.isMobileBrowse(request)) {
            return getViewPathH5("auth/binding-third");
        }
        return getViewPath("auth/binding-third");*/
    }

    //用于调整邦定页 测试代码
    //@RequestMapping("/test")
    public String formTest(HttpServletRequest request,
                              HttpServletResponse response) throws Exception {
        String comeUrl = "https://www.dwvan.com";
        UserThird userThird = new UserThird();
        userThird.setUserId(10000L);
        userThird.setName("启点学");
        userThird.setType(0);
        userThird.setAvatar("https://www.dwvan.com/static/images/logo.png");
        //来源地址设置到模版引擎
        request.setAttribute("comeUrl", comeUrl);
        //userThird
        request.setAttribute("userThird", userThird);
        //不需要跳转，直接模板
        if (TKRequest.isMobileBrowse(request)){
            return getViewPathH5("auth/binding-third");
        }
        return getViewPath("auth/binding-third");

    }
    /**
     * 第三方绑定新注册的账号(相当于注册操作)
     */
    @SuppressWarnings("unchecked")
    @RequestMapping("/binding")
    @ResponseBody
    public AjaxResult binding(HttpServletRequest request,
                                 HttpServletResponse response) throws Exception {
        String mobile = TKString.trim(request.getParameter("mobile"));
        if (TKString.isEmpty(mobile)) {
            return AjaxResult.error("手机号码不能为空！");
        }
        if (!TKString.isMobile(mobile)) {
            return AjaxResult.error("手机号码格式错误！");
        }
        //从缓存提取手机验证码
        String mobileCodeNum = (String) CacheUtils.get(CacheConstants.MOBILE_SMS_PRE + mobile);
        //获得输入的手机验证码
        String mobileCode = TKString.trim(request.getParameter("mobileCode"));
        //注册开关配置
        if (mobileCodeNum == null) {
            return AjaxResult.error("手机验证码已过期，请重新获取！");
        }
        if (mobileCode.length() < 5 || !mobileCode.equals(mobileCodeNum)) {
            return AjaxResult.error("请输入正确的手机验证码！");
        }
        CacheUtils.remove(CacheConstants.MOBILE_SMS_PRE + mobile);

        UserThird userThird = (UserThird) request.getSession().getAttribute(SESSION_PROFILE_NAME);
        if (userThird == null) {
            return AjaxResult.error("参数丢失，请重新发起绑定！");
        }
        User user = userService.getByMobile(mobile);
        if (user == null) {
            user = new User();
            user.setMobile(mobile);
            user.setUserName(userThird.getName());
            user.setRealName(userThird.getName());
            user.setAvatar(userThird.getAvatar());
            user.setPassword(TKString.getRanString(12));//用户用户密码
            user.setRegisterFrom(UserRegisterFrom.THIRD.toString());//用户注册来源 后台开通用户
            user.setIsAvailable(1);
            long userId = userService.register(request, user);
            if (userId < 1) {
                return AjaxResult.error("邦定失败！");
            }
        }
        userThird.setUserId(user.getUserId());
        //修改 userThird 的 userId
        userThirdService.update(userThird);
        //清理UserThird Session
        request.getSession().removeAttribute(SESSION_PROFILE_NAME);

        UserToken token = userService.doLogin(request, user);

        LoginUser.setUser(request, user);
        LoginUser.setCookie(response, token);

        return AjaxResult.success(user);
    }

    //从Session中获取ComeUrl
    private String getComeUrl(HttpSession session) {
        String comeUrl = (String) session.getAttribute(SESSION_COMEURL_NAME);
        if (comeUrl == null) {
            comeUrl = "/";
        } else {
            comeUrl = TKConvert.toURLDecode(comeUrl);
            if (comeUrl.contains("/auth/")) {
                comeUrl = "/";
            }
        }
        return comeUrl;
    }

    //清除Session，在设置登录信息之前清理
    private void clearLoginSession(HttpSession session) {
        session.removeAttribute(SESSION_STATE_NAME);
        session.removeAttribute(SESSION_COMEURL_NAME);
        session.removeAttribute(SESSION_PROFILE_NAME);
        session.invalidate();
    }
}
